﻿//给定一个长度为 n 的环形整数数组 nums ，返回 nums 的非空 子数组 的最大可能和 。
//环形数组 意味着数组的末端将会与开头相连呈环状。
//形式上， nums[i] 的下一个元素是 nums[(i + 1) % n] ， 
//nums[i] 的前一个元素是 nums[(i - 1 + n) % n] 。
//子数组 最多只能包含固定缓冲区 nums 中的每个元素一次。
//形式上，对于子数组 nums[i], nums[i + 1], ..., nums[j] ，
//不存在 i <= k1, k2 <= j 其中 k1 % n == k2 % n 。
//
//输入：nums = [1, -2, 3, -2]
//输出：3
//解释：从子数组[3] 得到最大和 3
//
//输入：nums = [5, -3, 5]
//输出：10
//解释：从子数组[5, 5] 得到最大和 5 + 5 = 10
//
//输入：nums = [3, -2, 2, -3]
//输出：3
//解释：从子数组[3] 和[3, -2, 2] 都可以得到最大和 3
//
//提示：
//	n == nums.length
//	1 <= n <= 3 * 10^4
//	- 3 * 10^4 <= nums[i] <= 3 * 10^4​​​​​​​

class Solution {
public:
    int maxSubarraySumCircular(vector<int>& nums) {
        // 1. 创建 dp 表
        // 2. 初始化
        // 3. 填表
        // 4. 返回结果
        int n = nums.size();
        vector<int> f(n + 1), g(n + 1);

        int fmax = INT_MIN, gmin = INT_MAX, sum = 0;
        for (int i = 1; i <= n; i++) {
            int x = nums[i - 1];
            f[i] = max(x, x + f[i - 1]);
            fmax = max(fmax, f[i]);
            g[i] = min(x, x + g[i - 1]);
            gmin = min(gmin, g[i]);
            sum += x;
        }
        return sum == gmin ? fmax : max(fmax, sum - gmin);
    }
};